package org.etcsoft.examples.jpa.repository.support;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;

import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

public class GenericRepositoryImpl<T, ID extends Serializable> extends
        SimpleJpaRepository<T, ID> implements GenericRepository<T, ID>,
        Serializable {
    private static final long serialVersionUID = 1L;

    private final JpaEntityInformation<T, ?> entityInformation;
    private final EntityManager em;
    private final DefaultPersistenceProvider provider;

    private Class<?> springDataRepositoryInterface;

    public Class<?> getSpringDataRepositoryInterface() {
        return this.springDataRepositoryInterface;
    }

    public void setSpringDataRepositoryInterface(Class<?> springDataRepositoryInterface) {
        this.springDataRepositoryInterface = springDataRepositoryInterface;
    }

    public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
            EntityManager entityManager, Class<?> springDataRepositoryInterface) {
        super(entityInformation, entityManager);
        this.entityInformation = entityInformation;
        this.em = entityManager;
        this.provider = DefaultPersistenceProvider.fromEntityManager(entityManager);
        this.springDataRepositoryInterface = springDataRepositoryInterface;
    }

    public GenericRepositoryImpl(Class<T> domainClass, EntityManager em) {
        this(JpaEntityInformationSupport.getMetadata(domainClass, em), em, null);
    }

    @Override
    public <S extends T> S save(S entity) {
        if (this.entityInformation.isNew(entity)) {
            this.em.persist(entity);
            this.flush();
            return entity;
        }
        entity = this.em.merge(entity);
        this.flush();
        return entity;
    }

    public T saveWithoutFlush(T entity) {
        return super.save(entity);
    }

    public List<T> saveWithoutFlush(Iterable<? extends T> entities) {
        List<T> result = new ArrayList<T>();
        if (entities == null) {
            return result;
        }

        for (T entity : entities) {
            result.add(this.saveWithoutFlush(entity));
        }
        return result;
    }

    /* (non-Javadoc)
     * @see kr.wisestone.owl.repository.GenericRepository#getEntityManager()
     */
    @Override
    public EntityManager getEntityManager() {
        return this.em;
    }
}
